﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ETWebApi2.Models
{
    
        /// <summary>
        /// 限制单个IP访问次数
        /// </summary>
        public class IPCacheHelper
        {
            /// <summary>         
            /// IP缓存集合          
            /// </summary>       
            private static List<IPCacheInfoModel> dataList = new List<IPCacheInfoModel>();

            private static object lockObj = new object();

            /// <summary>        
            /// 一段时间内，最大请求次数,必须大于等于1
            ///</summary> 
            private static int maxTimes = 1;

            /// <summary>  
            /// 一段时间长度（单位秒)，必须大于等于1     
            /// </summary>
            private static int partSecond = 1;

            /// <summary>  
            /// 请求被拒绝是否加入请求次数    
            /// </summary>  
            private static bool isFailAddIn = false;

            static IPCacheHelper()
            {

            }

            /// <summary>      
            /// 设置时间，默认maxTimes=3, partSecond=30         
            /// </summary>        
            /// <param name="_maxTimes">最大请求次数</param>        
            /// <param name="_partSecond">请求单位时间</param>         
            public static void SetTime(int _maxTimes, int _partSecond)
            {
                maxTimes = _maxTimes;
                partSecond = _partSecond;
            }

            /// <summary>    
            /// 检测一段时间内，IP的请求次数是否可以继续请求和使用  
            /// </summary>        
            /// <param name="ip">ip</param>   
            /// <returns></returns>       
            public static bool CheckIsAble(string ip)
            {
                lock (lockObj)
                {
                    var item = dataList.Find(p => p.IP == ip);
                    if (item == null)
                    {
                        item = new IPCacheInfoModel();
                        item.IP = ip;
                        item.ReqTime.Add(DateTime.Now);
                        dataList.Add(item);
                        return true;
                    }
                    else
                    {
                        if (item.ReqTime.Count > maxTimes)
                        {
                            item.ReqTime.RemoveAt(0);
                        }
                        var nowTime = DateTime.Now;
                        if (isFailAddIn)
                        {
                            #region 请求被拒绝也需要加入当次请求
                            item.ReqTime.Add(nowTime);
                            if (item.ReqTime.Count >= maxTimes)
                            {
                                if (item.ReqTime[0].AddSeconds(partSecond) > nowTime)
                                {
                                    return false;
                                }
                                else
                                {
                                    return true;
                                }
                            }
                            else
                            {
                                return true;
                            }
                            #endregion
                        }
                        else
                        {
                            #region 请求被拒绝就不需要加入当次请求了
                            if (item.ReqTime.Count >= maxTimes)
                            {
                                if (item.ReqTime[0].AddSeconds(partSecond) > nowTime)
                                {
                                    return false;
                                }
                                else
                                {
                                    item.ReqTime.Add(nowTime);
                                    return true;
                                }
                            }
                            else
                            {
                                item.ReqTime.Add(nowTime);
                                return true;
                            }
                            #endregion
                        }
                    }
                }
            }


            /// <summary>    
            /// 检测一段时间内，IP的请求次数是否可以继续请求和使用  
            /// </summary>        
            /// <param name="ip">ip</param>   
            /// <returns></returns>       
            public static IPCacheInfoModel GetIPLimitInfo(string ip)
            {
                lock (lockObj)
                {
                    var item = dataList.Find(p => p.IP == ip);
                    if (item == null) //IP开始访问
                    {
                        item = new IPCacheInfoModel();
                        item.IP = ip;
                        item.ReqTime.Add(DateTime.Now);
                        dataList.Add(item);
                        item.IsVisit = true; //可以继续访问

                        return item;
                    }
                    else
                    {
                        if (item.ReqTime.Count > maxTimes)
                        {
                            item.ReqTime.RemoveAt(0);
                        }
                        var nowTime = DateTime.Now;
                        if (isFailAddIn)
                        {
                            #region 请求被拒绝也需要加入当次请求
                            item.ReqTime.Add(nowTime);

                            if (item.ReqTime.Count >= maxTimes)
                            {
                                if (item.ReqTime[0].AddSeconds(partSecond) > nowTime)
                                {
                                    item.Limit++; //限制次数+1
                                    item.IsVisit = false;//不能继续访问
                                    return item;
                                }
                                else
                                {
                                    item.IsVisit = true; //可以继续访问
                                    return item; //单个IP30秒内 没有多次访问
                                }
                            }
                            else
                            {
                                item.IsVisit = true; //可以继续访问
                                return item; //单个IP访问次数没有达到max次数
                            }
                            #endregion
                        }
                        else
                        {
                            #region 请求被拒绝就不需要加入当次请求了
                            if (item.ReqTime.Count >= maxTimes)
                            {
                                if (item.ReqTime[0].AddSeconds(partSecond) > nowTime)
                                {
                                    item.Limit++; //限制次数+1
                                    item.IsVisit = false;//不能继续访问

                                    return item;
                                }
                                else
                                {
                                    item.ReqTime.Add(nowTime);

                                    item.IsVisit = true; //可以继续访问
                                    return item;
                                }
                            }
                            else
                            {
                                item.ReqTime.Add(nowTime);
                                item.IsVisit = true; //可以继续访问

                                return item;
                            }
                            #endregion
                        }
                    }
                }
            }
        }
    }
